//
// Created by suzhen on 18-1-16.
//

#pragma once

#include <hacks/base/hacks_conf.h>

namespace hacks::net {

    typedef std::list<char> buff_ls_t;
    typedef std::vector<char> buff_vec_t;

    typedef std::function<void(ssize_t)> progress_functor_t;
    typedef std::function<void()> complete_functor_t;

    struct const_buffer {
        buff_vec_t buff{};
        std::size_t w_idx{0};
        progress_functor_t progress_fun{nullptr};
        complete_functor_t complete_fun{nullptr};

        void on_complete() {
            if (complete_fun) { complete_fun(); }
        }

        void on_progress(ssize_t progress) {
            if (progress_fun) { progress_fun(progress); }
        }
    };

    typedef std::list<const_buffer> const_buffer_list_t;

    class mutable_data_buffer {

    public:
        mutable_data_buffer() : data_list_() {}

        void write_buff(const char *data, std::size_t len) {
            for (auto it = data; it != data + len; ++it) {
                data_list_.emplace_back(*it);
            }
        }

        buff_vec_t read_data(std::size_t sz) {
            assert(readable_size() <= sz);
            buff_vec_t ret(sz);
            for (auto i = 0; i < sz; ++i) {
                ret[i] = data_list_.front();
                data_list_.pop_front();
            }
            return ret;
        }

        buff_vec_t peek_data(std::size_t sz) {
            assert(readable_size() <= sz);
            buff_vec_t ret(sz);
            auto i = 0;
            for (auto it = data_list_.begin();
                 it != data_list_.end() && i < sz;
                 ++i, ++it) {
                ret[i] = *it;
            }
            return ret;
        }

        std::size_t readable_size() const {
            return data_list_.size();
        }

    private:
        buff_ls_t data_list_;
    };
}



